package flexo.common;

import org.lwjgl.*;

/**
*
* A hires timer. This measures time in seconds as floating point values.
* All Timers created are updated simultaneously by calling the static method
* tick(). This ensures that within a single iteration of a game loop that
* all timers are updated consistently with each other.
* 
* @author cix_foo <cix_foo@users.sourceforge.net>
* @version $Revision: 2286 $
*/
public class Timer
{
	// Record the timer resolution on classload
	private static long resolution = Sys.getTimerResolution();
	
	// Every so often we will re-query the timer resolution
	private static final int QUERY_INTERVAL = 50; // in calls to tick()
	private static int queryCount = 0;

	// Globally keeps track of time for all instances of Timer	
	private static long currentTime;
	
	// When the timer was started
	private long startTime;
	
	// The last time recorded by getTime()
	private long lastTime;

	// Whether the timer is paused
	private boolean paused;
		
	static {
		tick();
	}
	
	/**
	 * Constructs a timer. The timer will be reset to 0.0 and resumed immediately.
	 */
	public Timer() {
		reset();
		resume();
	}
	
	/**
	 * @return the time in seconds, as a float
	 */
	public float getTime() {
		if (!paused) {
			lastTime = currentTime - startTime;
		}

		return (float) ((double) lastTime / (double) resolution);
	}
	/**
	 * @return whether this timer is paused
	 */
	public boolean isPaused() {
		return paused;
	}
	
	/**
	 * Pause the timer. Whilst paused the time will not change for this timer
	 * when tick() is called.
	 * 
	 * @see #resume()
	 */
	public void pause() {
		paused = true;
	}
	
	/**
	 * Reset the timer. Equivalent to set(0.0f);
	 * @see #set(float)
	 */
	public void reset() {
		set(0.0f);
	}
	
	/**
	 * Resume the timer.
	 * @see #pause()
	 */
	public void resume() {
		paused = false;
		startTime = currentTime - lastTime;
	}
	
	/**
	 * Set the time of this timer
	 * @param newTime the new time, in seconds
	 */
	public void set(float newTime) {
		long newTimeInTicks = (long) ((double) newTime * (double) resolution);
		startTime = currentTime - newTimeInTicks;
		lastTime = newTimeInTicks;
	}
	
	/**
	 * Get the next time update from the system's hires timer. This method should
	 * be called once per main loop iteration; all timers are updated simultaneously
	 * from it.
	 */
	public static void tick() {	
		currentTime = Sys.getTime();
		
		// Periodically refresh the timer resolution:
		queryCount ++;
		if (queryCount > QUERY_INTERVAL) {
			queryCount = 0;
			resolution = Sys.getTimerResolution();
		}
	}
	
	/**
	 * Debug output.
	 */
	public String toString() {
		return "Timer[Time=" + getTime() + ", Paused=" + paused + "]";
	}
}
